/**
 * Company:湖南省汇聚赢农业开发有限公司
 */

package com.hunhjy.wx.wxsdk.api;

import java.util.Map;
import java.util.concurrent.Callable;

import com.hunhjy.core.kit.ParaMap;
import com.hunhjy.core.kit.RetryUtils;
import com.hunhjy.wx.wxsdk.AccessToken;
import com.hunhjy.wx.wxsdk.WxAccount;
import com.hunhjy.wx.wxsdk.cache.IAccessTokenCache;
import com.hunhjy.wx.wxsdk.util.HttpUtils;

/**
 * @Description: TODO
 * @author ZhuoQi_Zou
 * @date 2016年6月25日 下午11:48:52
 *
 */

public class AccessTokenApi {

	// "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	private static String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";

	// 利用 appId 与 accessToken 建立关联，支持多账户
	static IAccessTokenCache accessTokenCache = ApiConfigKit.getAccessTokenCache();

	/**
	 * 从缓存中获取 access token，如果未取到或者 access token 不可用则先更新再获取
	 * 
	 * @return AccessToken accessToken
	 */
	public static AccessToken getAccessToken() {
		String appId = ApiConfigKit.getWxAccount().getAppId();
		AccessToken result = accessTokenCache.get(appId);
		if (result != null && result.isAvailable())
			return result;

		refreshAccessToken();
		return accessTokenCache.get(appId);
	}

	/**
	 * 直接获取 accessToken 字符串，方便使用
	 * 
	 * @return String accessToken
	 */
	public static String getAccessTokenStr() {
		return getAccessToken().getAccess_token();
	}

	/**
	 * 强制更新 access token 值
	 */
	public static synchronized void refreshAccessToken() {
		WxAccount ac = ApiConfigKit.getWxAccount();
		String appId = ac.getAppId();
		String appSecret = ac.getAppSecret();
		final Map<String, String> queryParas = ParaMap.create("appid", appId)
									.put("secret", appSecret).getData();

		// 最多三次请求
		AccessToken result = RetryUtils.retryOnException(3,
					new Callable<AccessToken>() {

			@Override
			public AccessToken call() throws Exception {
				String json = HttpUtils.get(url, queryParas);
				return new AccessToken(json);
			}
		});

		// 三次请求如果仍然返回了不可用的 access token 仍然 put 进去，便于上层通过 AccessToken 中的属性判断底层的情况
		accessTokenCache.set(ac.getAppId(), result);
	}

}
